package com.jiang.thread.pool;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @author jiangzhe
 * @create 2022/5/11 13:27
 */
@Slf4j
public class TestThreadPool {

    @Test
    public void test2() throws ExecutionException, InterruptedException {
        int count = 0;
        Instant start = Instant.now();
        List<Machine> machines = getAllMachines();
        List<Node> allNodes = getAllNodes();
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        List<Callable<Integer>> tasks = new ArrayList<>();
        for (Machine machine: machines) {
            Callable<Integer> task = () -> {
                int errorNodeInMachine = 0;
                List<Node> nodesInMachine = allNodes.stream().filter(n -> (n.getMachineId() == machine.getId())).collect(Collectors.toList());
                log.info("start check nodes in machine {}", machine.getName());
                for (Node node: nodesInMachine) {
                    Thread.sleep(500);
                    if("node2".equals(node.getName())){
                        errorNodeInMachine += 1;
                        node.setStatus(1);
                    }
                }
                return errorNodeInMachine;
            };
            tasks.add(task);
        }
        List<Future<Integer>> futures = new ArrayList<>();
        for (Callable<Integer> task: tasks) {
            futures.add(executorService.submit(task));
        }
        for (Future<Integer> future: futures) {
            count += future.get();
        }
        log.info("count abnormal node: {}, time cost: {}", count, Duration.between(start, Instant.now()).toMillis());
        log.info(allNodes.stream().filter(n -> n.getStatus()==1).collect(Collectors.toList()).toString());
    }

    @Data
    @AllArgsConstructor
    class Machine{
        Integer id;
        String name;
    }

    @Data
    @AllArgsConstructor
    class Node{
        int machineId;
        String name;
        int status;
    }

    public List<Machine> getAllMachines(){
         return Arrays.asList(
                 new Machine(1, "m1"),
                 new Machine(2, "m2"),
                 new Machine(3, "m3"),
                 new Machine(4, "m4")
         );
    }

    public List<Node> getAllNodes(){
        List<Node> allNodes = new ArrayList<>();
        for (int machineId = 1; machineId <= 4; machineId++) {
            allNodes.addAll(
                    Arrays.asList(
                            new Node(machineId, "node0", 0),
                            new Node(machineId, "node1", 0),
                            new Node(machineId, "node2", 0),
                            new Node(machineId, "node3", 0),
                            new Node(machineId, "node4", 0),
                            new Node(machineId, "node5", 0)
                    )
            );
        }
        return allNodes;
    }
}
